package com.xhwl.centiotdata.suppliersystem.keytopLocal;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.xhwl.centiotdata.pojo.constant.KeyTopLocalConstant;
import com.xhwl.centiotdata.pojo.dto.keytoplocal.AccessInfoKeyTopLocalDTO;
import com.xhwl.centiotdata.pojo.dto.pedestrian.PedestrianIntegrationConfigDTO;
import com.xhwl.centiotdata.service.cent.IAccountCentService;
import com.xhwl.centiotdata.service.cent.IAuthAccountCentService;
import com.xhwl.centiotdata.utils.Base64Utils;
import com.xhwl.common.dto.auth.PedestrianAuthDTO;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.dto.cent.pedes.OpenDoorRecordDTO;
import com.xhwl.common.enums.AccessTypeEnum;
import com.xhwl.common.enums.ProductEnum;
import com.xhwl.common.enums.SourceTypeEnum;
import com.xhwl.common.enums.pedestrian.DoorActionEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.auth.AuthAccountMapping;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.query.cent.sdata.AccountQuery;
import com.xhwl.common.utils.ChkUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @author msy
 * @description 对接科拓人行2.0-本地
 */
@Service
@Slf4j
public class PedestrianKeyTopLocalHandler {

    @Autowired
    private IAccountCentService accountCentService;

    @Autowired
    private GeneralKeyTopLocalHandler generalKeyTopLocalHandler;

    @Autowired
    private IAuthAccountCentService authAccountCentService;


    public List<OpenDoorRecordDTO> handleRecord(AccessInfoKeyTopLocalDTO record, PedestrianIntegrationConfigDTO config) {
        List<OpenDoorRecordDTO> openDoorRecordDTOList = new ArrayList<>();
        String picUrl = null;
        if(ChkUtil.isNotNull(record.getFacePhotoAddr())) {
            picUrl = config.getIpAndPort() + record.getFacePhotoAddr();
        }
        OpenDoorRecordDTO openDoorRecordDTO = OpenDoorRecordDTO.builder()
                .projectId(config.getProjectId())
                .productId(ProductEnum.KEYTOP_LOCAL.getId())
                .openUserId(record.getStaffId())
                .userName(record.getStaffName())
                .openDeviceId(record.getDoorId())
                .deviceName(record.getDoorName())
                .code(record.getId())
                .arrivalTime(DateUtil.formatDateTime(record.getTime()))
                .pictureUrl(picUrl)
                .state((short) (Integer.valueOf(1).equals(record.getPassType()) ? 1 : 0))
                .type(handleAccessType(record.getPassMode()))
                .direction((short) (Integer.valueOf(1).equals(record.getReadType()) ? 1 : 2))
                .build();
        // 目前科拓本地对接的接口不支持业主使用二维码开门，所以默认使用二维码开门的是访客
        if(openDoorRecordDTO.getType().equals(AccessTypeEnum.QR_CODE.getId())) {
            openDoorRecordDTO.setSourceType(SourceTypeEnum.VISITOR_USER.getType());
        } else {
            openDoorRecordDTO.setSourceType(SourceTypeEnum.USER.getType());
        }
        openDoorRecordDTOList.add(openDoorRecordDTO);
        return openDoorRecordDTOList;
    }

    public Short handleAccessType(String type) {
        switch (type) {
            case KeyTopLocalConstant.FACE:
                return AccessTypeEnum.FACE.getId();
            case KeyTopLocalConstant.CARD:
                return AccessTypeEnum.IC_CARD.getId();
            case KeyTopLocalConstant.QRCODE:
                return AccessTypeEnum.QR_CODE.getId();
            case KeyTopLocalConstant.FINGERPRINT:
                return AccessTypeEnum.FINGERPRINT.getId();
            case KeyTopLocalConstant.PUBLIC_PASSWORD:
                return AccessTypeEnum.PASS_WORD.getId();
            default:
                return AccessTypeEnum.OTHER.getId();
        }
    }

    public AuthAccountMapping createUser(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        Integer projectId = configDTO.getProjectId();
        Integer productId = configDTO.getProductId();
        Integer accountId = pedestrianAuthDTO.getSourceId();

        AccountQuery accountQuery = new AccountQuery();
        accountQuery.setId(accountId);
        Account account = accountCentService.getAccount(null, accountQuery);
        if(account == null){
            throw new BusinessException("不存在该人员！");
        }

        Map<String, Object> params = new HashMap<>();
        // 科拓：0.男 1.女
        params.put("gender", Integer.valueOf(0).equals(account.getSex()) ? 1 : 0);
        params.put("name", account.getName());
        params.put("validFrom", DateUtil.formatDate(pedestrianAuthDTO.getValidStartTime()));
        params.put("validTo", DateUtil.formatDate(pedestrianAuthDTO.getValidEndTime()));

        String orgId = null;
        AuthAccountMapping authAccountMapping = authAccountCentService.query(projectId, productId, accountId);
        // 已经同步过该人员
        if(authAccountMapping != null) {
            JSONObject staff = queryStaffById(configDTO, authAccountMapping.getOpenId());
            orgId = staff.getStr("orgId");
            params.put("id", authAccountMapping.getOpenId());
        } else {
            orgId = queryOrganization(configDTO);
        }
        params.put("orgId", orgId);

        JSONObject result = generalKeyTopLocalHandler.post(KeyTopLocalConstant.SAVE_STAFF, params, projectId,
                productId, configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
        JSONObject data = result.getJSONObject("data");
        String openId = data.getStr("id");

        AuthAccountMapping add = new AuthAccountMapping();
        add.setOpenId(openId);
        add.setAccountId(accountId);
        add.setProductId(configDTO.getProductId());
        add.setProjectId(configDTO.getProjectId());
        authAccountCentService.save(configDTO.getProjectId(), pedestrianAuthDTO.getSourceId(), openId, null ,configDTO.getProductId());
        return add;
    }


    private JSONObject queryStaffById(PedestrianIntegrationConfigDTO configDTO, String id) {
        Map<String, Object> params = new HashMap<>();
        params.put("id", id);

        JSONObject result = generalKeyTopLocalHandler.post(KeyTopLocalConstant.QUERY_STAFF_BY_ID, params, configDTO.getProjectId(),
                configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());

        JSONObject data = result.getJSONObject("data");
        return data;
    }


    private String queryOrganization(PedestrianIntegrationConfigDTO configDTO) {
        JSONObject result = generalKeyTopLocalHandler.post(KeyTopLocalConstant.ORG_LIST, null, configDTO.getProjectId(),
                configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
        JSONArray data = result.getJSONArray("data");
        String orgId = null;

        // 如果组织为空，则需要先新增组织
        if(ChkUtil.isNull(data)) {
            // 新增组织
            Map<String, Object> params = new HashMap<>();
            params.put("orgName", KeyTopLocalConstant.ORGANIZATION_NAME);
            params.put("pid", 0);

            JSONObject saveOrgJsonObject = generalKeyTopLocalHandler.post(KeyTopLocalConstant.SAVE_ORG, params, configDTO.getProjectId(),
                    configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
            JSONObject orgData = saveOrgJsonObject.getJSONObject("data");
            orgId = orgData.getStr("id");
        } else {
            JSONObject org = new JSONObject(data.get(0));
            orgId = org.getStr("id");
        }
        return orgId;
    }


    public void addFace(String openId, String faceUrl, PedestrianIntegrationConfigDTO configDTO) {
        String faceBase = Base64Utils.getBaseByUrl(faceUrl);
        Map<String, Object> params = new HashMap<>();
        params.put("faceBase64", faceBase);
        params.put("staffId", openId);

        generalKeyTopLocalHandler.post(KeyTopLocalConstant.SAVE_OCR, params, configDTO.getProjectId(),
                configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
    }


    public void saveAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        List<String> thirdDeviceIdList = pedestrianAuthDTO.getThirdDeviceIdList();
        if(CollectionUtils.isEmpty(thirdDeviceIdList)){
            log.error("没有要授权的第三方设备！！");
            return;
        }

        String userOpenId = pedestrianAuthDTO.getUserOpenId();
        JSONObject staff = queryStaffById(configDTO, userOpenId);
        if(staff == null) {
            AuthAccountMapping authAccountMapping = createUser(configDTO, pedestrianAuthDTO);
            userOpenId = authAccountMapping.getOpenId();
        }

        Map<String, Object> params = new HashMap<>();
        params.put("staffId", userOpenId);
        params.put("doorIds", thirdDeviceIdList);

        generalKeyTopLocalHandler.post(KeyTopLocalConstant.ADD_DOOR_AUTHORIZE, params, configDTO.getProjectId(),
                configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
    }


    public void deleteAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        String userOpenId = pedestrianAuthDTO.getUserOpenId();
        JSONObject staff = queryStaffById(configDTO, userOpenId);
        if(staff == null) {
            log.error("删除授权时，科拓系统中没有该人员！");
            return;
        }

        List<String> thirdDeviceIdList = pedestrianAuthDTO.getThirdDeviceIdList();
        if(CollectionUtils.isEmpty(thirdDeviceIdList)){
            log.error("没有要删除授权的第三方设备！！");
            return;
        }

        Map<String, Object> deleteDoorAuthParams = new HashMap<>();
        deleteDoorAuthParams.put("staffId", userOpenId);
        deleteDoorAuthParams.put("doorIds", thirdDeviceIdList);
        generalKeyTopLocalHandler.post(KeyTopLocalConstant.DELETE_DOOR_AUTHORIZE, deleteDoorAuthParams, configDTO.getProjectId(),
                configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
        log.info("科拓删除人员门禁权限成功！");

        Map<String, Object> deleteStaffParams = new HashMap<>();
        deleteStaffParams.put("id", userOpenId);
        generalKeyTopLocalHandler.post(KeyTopLocalConstant.DELETE_STAFF_BY_ID, deleteStaffParams, configDTO.getProjectId(),
                configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
        log.info("科拓删除人员成功！");
    }

    public ResultJson openDoor(PedestrianIntegrationConfigDTO configDTO, DeviceDTO deviceDTO, DoorActionEnum doorAction) {
        Integer status;
        switch (doorAction) {
            case REMOTELY_OPEN:
                status = 1;
                break;
            case NORMALLY_OPEN:
                status = 3;
                break;
            case NORMALLY_CLOSE:
                status = 4;
                break;
            default:
                return ResultJson.fail("无对应设备操作");
        }

        Map<String, Object> params = new HashMap<>();
        params.put("status", status);
        params.put("doorIds", Arrays.asList(deviceDTO.getThirdDeviceId()));
        try {
            generalKeyTopLocalHandler.post(KeyTopLocalConstant.DOOR_CONTROL, params, configDTO.getProjectId(),
                    configDTO.getProductId(), configDTO.getIpAndPort(), configDTO.getLoginName(), configDTO.getPassword());
        } catch (Exception e) {
            log.error("远程开门操作失败： {}", params);
            return ResultJson.fail("远程开门操作失败");
        }
        return ResultJson.success();
    }
}
